package org.simpleProxy;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ftpserver.FtpServer;
import org.apache.ftpserver.FtpServerFactory;
import org.apache.ftpserver.ftplet.Authority;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.ftplet.Ftplet;
import org.apache.ftpserver.ftplet.UserManager;
import org.apache.ftpserver.listener.ListenerFactory;
import org.apache.ftpserver.usermanager.ClearTextPasswordEncryptor;
import org.apache.ftpserver.usermanager.PropertiesUserManagerFactory;
import org.apache.ftpserver.usermanager.impl.BaseUser;
import org.apache.ftpserver.usermanager.impl.WritePermission;
import org.apache.log4j.Logger;

public class Server {

	private String defaultUser = "ftpproxy";
	private String defaultPass = "password";
	static Logger classLogger = Logger.getLogger(Server.class.getName());
	private FtpServer server;
	
	public Server(File configFile, int port, String ftpFolder) throws IOException, FtpException {
		
		//Default Variables
		PropertiesUserManagerFactory pFac = new PropertiesUserManagerFactory();
		FtpServerFactory sFac = new FtpServerFactory();
		ListenerFactory lFac = new ListenerFactory();
		boolean hasDefaultUser = false;
		
		
		//if the configuration does not exist, make a new one
		if(!configFile.exists()){
			classLogger.info("Could not find users.properties file - proceeding to create one");
			try {
				configFile.createNewFile();
			}
			catch(IOException e){
				throw new IOException("Could not create properties File");
			}
		}
		
		//Use the users.properties file - in the future we should use salted md5
		//TODO: make this configurable
		pFac.setFile(new File("users.properties"));
		pFac.setPasswordEncryptor(new ClearTextPasswordEncryptor());
		
		//Bind the user manager to the one we need
		//Also set up the login if necessary
		UserManager um = setupLoginForDefaultUser(pFac, hasDefaultUser, ftpFolder);
		
		//Set the options
		lFac.setPort(port);
		sFac.setUserManager(um);
		sFac.addListener("default", lFac.createListener());
		Map<String, Ftplet> ftplets = new HashMap<String, Ftplet>();
		ftplets.put("LuceneFTPlet", new LuceneFTPlet(ftpFolder));
		sFac.setFtplets(ftplets);
		this.server = sFac.createServer();
	}

	
	/*
	 * Create default login if necessary, otherwise just set required options on the 
	 * User manager and return
	 */
	private UserManager setupLoginForDefaultUser( PropertiesUserManagerFactory pFac, boolean hasDefaultUser, String ftpFolder)
			throws FtpException {
		
		
		UserManager um = pFac.createUserManager();
		
		// If the default username is not in the list, add it
		for( String userName : um.getAllUserNames()){
			if(userName.equals(defaultUser)){
				hasDefaultUser = true;
			}
			//If the users dont have the correct home directory, change it
			if(!um.getUserByName(userName).getHomeDirectory().equals(ftpFolder)){
				BaseUser editUser = (BaseUser) um.getUserByName(defaultUser);
				editUser.setHomeDirectory(ftpFolder);
			}
		}
		
		// Creating the user
		if(!hasDefaultUser){
			
			//Give the user write permissions of the basic stuff
			BaseUser user = new BaseUser();
			user.setName(defaultUser);
			user.setPassword(defaultPass);
			user.setHomeDirectory(ftpFolder);
			List<Authority> auths = new ArrayList<Authority>();
			auths.add(new WritePermission());
			user.setAuthorities(auths);
			um.save(user);
			classLogger.info("Could not find default user - adding it into the user.properties file");
		
		}
		return um;
	}
	
	public void start() throws FtpException{
		this.server.start();
	}
	
	public void stop(){
		this.server.stop();
	}
}
